#include <string>
#include <iostream>
#include <cstdint>
#include <algorithm>
#include <iterator>
#include <memory>
#include <cstdint>
#include <vector>
#include <queue>
#include <stack>

#include "Header.h"
#include "Class.h"
#include "deduction guide.h"
using namespace std;

int main()
{
	
	//////////////////////////////////////////////////////////////////////////////////////////////
	//������� 1. ���������� ���������� ���������� � ������� constexpr-�������.
	//
	//���������/�����������: 
	//		- constexpr � ������� ������ �������� �� ������������ ���������� return <���������>; (����!)
	//		- �� ��� ��������� ����� �������� ����� ������ constexpr � �������, � ��������� �����������
	//		  ����� 
	//		- ���� �������� ����������� constexpr- ������� - ��� ���������, ���������� �������� ���������
	//		  �� ����� ����������

	//��������� ��� ����, ��� ���������� ��������� �������� �� ����� ���������� (���� � ��������
	//				��������� ������������ ���������, ��������� ����������� �� ����� ����������).
	//				��� �������� ���������� ������� ���������� ������ � ������������, �����������
	//				����������� constexpr-�������:

	{	//��������:
		int ar[factorial(3)];
		auto iter = begin(ar);
		//���
		constexpr int n = factorial(5);
		int ar1[n];
		auto iter1 = begin(ar1);
		//����������:
		int m = 7;
		//constexpr int n1 = factorial(m);
		//int ar1[n1];

		//� ���?
		int n2 = factorial(m);
		__asm nop
	}

	//////////////////////////////////////////////////////////////////////////////////////////////
	//������� 2a. ������� � ������� ����������������� �������� �� ��������� ������������� ����������
	//� ��������, ��������: ������ "100000000" -> � �������� 256
	//��������� ��������� ����������� �������� 0b
	//����� ����� ����������������� �������� �������� ������ � �������, ��������: 100000000_b
	//������� ������������ ���������������� ������� � ������������ ���������� - const char*

	//��� ��� ���� ���� � ���������, ������� ��������� �������� �� ����� ����������
	// => ���������� ���������������� ������� ����������� constexpr - �������
	//���������/�����������: 
	//		- constexpr � ������� ������ �������� �� ������������ ���������� return <���������>;
	//		- �� ��� ��������� ����� �������� ����� ������ constexpr � �������,
	//		- ������� ����� ���� ����������� (���� �������� ����� ������� - ��� ���������,
	//		  ���������� �������� ��������� ������ ����������� ������� �� ����� ����������)

	{
		//constexpr int n1 = myStrlen("100000000");//9
		//int x1 = myStrlen("100000000");
		//constexpr int n2 = ToInt('1');//1
		//int x2 = ToInt('1');
		//constexpr int n3 = ToInt('0');//0
		//int x3 = ToInt('0');
		//constexpr int n4 = myPow(2, n1 - 1);//256
		//int x4 = myPow(2, n1 - 1);
		constexpr unsigned long long n5 = 100000001_b;//257
		unsigned long long x5 = 100000001_b;
		int rrr5 = 0b100000001;

		constexpr unsigned long long n6 = 101_b;//5
		unsigned long long x6 = 101_b;
		int rrr6 = 0b101;

		//273
		constexpr unsigned long long n7 = 100010001_b;
		unsigned long long x7 = 100010001_b;
		int rrr1 = 0b100010001;
		
		//256
		constexpr unsigned long long n = 100000000_b;
		unsigned long long x = 100000000_b;
		int rrr = 0b100000000;
		
		//346
		constexpr unsigned long long n8 = 101011010_b;
		unsigned long long x8 = 101011010_b;
		int rrr8 = 0b101011010;

		__asm nop

	}

	//������� 2b. ������� � ��������� �������� �������������, ��������: 256 -> "0b100000000"
	//��� ��� ������ ����� ���� ����� �����, �������� � ����� ���������� ������ std::string
	//=> ������������ �������� �� ����� ���� constexpr!
	//���������: ������������ std::bin ���� ��� => �������������� � �������� ������
	//�������� ������ �������
	//���������: ���������� �������� � ����� ���������� ��������� CHAR_BIT - <cstdint>

	{
		std::string sBin= 256_toBinStr;
		std::string sBin1 = 5_toBinStr;
		std::string sBin2 = 346_toBinStr;
		std::string sBin3 = 0_toBinStr;
		__asm nop
	}


	//////////////////////////////////////////////////////////////////////////////////////////////
	//������� 3. constexpr - ������� 
	//������� ����� (������ ������?) ��� �������� � ��������������� ���������� ��������.
	//� ������ ������ ����:
	//	���������� ��� �������� ������������ � ������������� ��������,
	//	������ ��� ��������� ������� �� ��������
	//	����� ��� �������� - �������� �� ��������� �������� � ��������
	//	�����, ������� �������� ����� �������� ������� ���� � ��������� �������������� ��������:
	//							���� ����������� ���������, �� ��� � ����������
	//							���� ������ ������������ ��������, ���������� �����������
	//							���� ������ ������������� ��������, ���������� ������������

	//��������� ��� ����, ��� ���������� ��������� �������� �� ����� ����������. 

	{
		constexpr range<int> r;
		constexpr range<double> r1 (14,7);
		range<double> r2(14, 7);
		constexpr range<char> r3('f', 'l');
		constexpr range<int> r4(88,11);

		constexpr double d = r1.Get_max();
		constexpr char ch = r3.Get_min();

		constexpr int res = r4.in_range(12);
		int RTTI_res = r4.in_range(12);
		constexpr int res1 = r4.in_range(11);
		constexpr int res2 = r4.in_range(10);
		constexpr int res3 = r4.in_range(88);
		constexpr int res4 = r4.in_range(89);
		__asm nop
	}
	/***************************************************************/
//������� 4.
	/*
	���������� ������ ������� ��� ������ ����� ������������������� (vector, list, deque, set � ����������� �������), ������� ����� ���������:
	�	��� ������� ������ ����,
	�	��� � ��������� �� ������� ������ ���� (��������� ������������� ����������� => � ���� ������ ������� �������� �������� �� ������)
	���������: if constexpr
	*/
	{	
		int x = 1, y = 2, z = 3;
		vector<int> v{ 1,2,3 };
		vector<int*> v1{ &x,&y,&z };
		string arr[3]{"Hi","May","Go"};
		string a = "Hi", b = "May", c = "Go";
		string* arr1[3]{&a, &b,&c};
		vector<string*> v_str{new string("Hi"),new string("May"), new string("Go")};

		cout << "__vector<int>__" << endl;
		print_container(v);
		cout << "__vector<int*>__" << endl;
		print_container(v1);
		cout << "__string arr[3]__" << endl;
		print_container(arr);
		cout << "__string* arr[3]__" << endl;
		print_container(arr1);
		cout << "__vector<string*>__" << endl;
		print_container(v_str);
		__asm nop
	}

	/***************************************************************/
	//������� 5.
		/* ���������� ������ ������� �������� ���� ��������.
		���� ������ ��������� �������� ��������, �� ��� �������� ������� ����� ��������� �� �������� ������� ���������. ��� ���� �������� ������� � ������ �������� ������ ���� ������ � ���� �� ����.
		���������: if constexpr, is_same
		*/
	{
		vector<int> vec{ 5,7,8,9,10 };
		string str{ "Yonk" };
		string str1{ "Svoper" };

		auto x = addition(1,5);
		auto x1 = addition(55,0.3);
		auto x2 = addition(vec, 5);
		//auto x3 = addition(vec, 5.0);
		auto x4 = addition(str, str1);
		//auto x5 = addition(str,5);
		auto x5 = addition("Yonk",5);//!!! ���������� ���������
		__asm nop
	}


	/***************************************************************/
//������� 6.
	/* 	���������� ������ ������� ������ �� ������ �������� ��������� ������ �������� (stack, queue, priority_queue)
	���������: if constexpr, is_same
	������������� ����� ��������, ���� � �������� �������� ���������.
	*/
	{
		deque<int>d{ 0,1,2,3,4,5,6 };
		stack<int> s_int(d);

		print_adapter(s_int);

		deque<string>d1{ "zero", "one", "two", "three" };
		queue<string>q_str(d1);

		print_adapter(q_str);

		vector<string>v{ "www", "ttt", "AAA", "kkk", "aaa", "WWW", "TTT", "KKK" };
		priority_queue<string>p_q_str(v.begin(), v.end());

		print_adapter(p_q_str);

		int x = 1, y = 2, z = 3;
		vector<int*> v1{ &x,&y,&z };
		priority_queue<int*>p_q_i(v1.begin(), v1.end());
		print_adapter(p_q_i);
		__asm nop
	}

	/***************************************************************/
//������� 7.
	/* 	���������� ������ constexpr ������� Smth(), ������� ������ ���������� �������� ������� ����
	���������: constexpr, if constexpr
	*/
	constexpr int res1 = /*<�����;*/ Smth<int>();/*>*/ //res1 = 1
	constexpr double res2 = /*<�����*/ Smth<double>();/*>; */ //res2 = 2.2
	/*constexpr*/ std::string res3 = /*<����� */ Smth<string>()/*>*/; //res3 = "abc"

	//***************************************************************/
	//������� 8.

		/*���������������� deduction guide � ��� ������ ����� ���������� �������
		����� ������ ������, ������� ������������� ���������� ������������ ������ ���������
		����������� � ���������� ������ ����. */
		/*
		template<typename T, size_t size> class MyArray
			{
				T ar[size]; //��� ���������� ������������� ��������� �������� ���� �� ��������� �����?
				�
				public:
				MyArray(const T*[, �������� ������ ���������]);


			};

		*/
		
		//��������� ���������� ����������������� ����������� �������� �������������.
			{
				MyArray<int, 5> ar1;//MyArray<int,5>
				MyArray<char, 5> ar2{"ABCqwerty"};//MyArray<char,5>

				MyArray ar3{"ABC"}; //MyArray<char,4>

				int ar[] = { 1,2,3 };
				MyArray ar4{ ar };//MyArray<int,3>
				__asm nop
			}
	


}
